<?php
/**
 * httprequest class
 * 
 * http request class from client
 * @date 2012.6.19
 * @author qixiaona@gmail.com
 * @dependency NICED_ExceptionHandler
 * @package NICED
 * 
 */
class NICED_HttpRequest extends NICED_HttpBase
{

    protected $requestMethod;
    protected $requestBody;
    protected $headers    = array();
    protected $params     = array();
    protected $handler;

    protected $paramConfig   = array();
    protected $requestMethods= array("GET", "POST");
    protected $acceptVars    = array("POST", "GET");//POST, GET, BODY,has order, should GET at first, POST will override param from GET
    protected $formats       = array("json", "xml");

    protected $defaultFormat   = "json";

    public function __construct()
    {
        $this->initHandler();
    }

    /**
     * init class
     * @access public
     * @return bool
     *
     */
    public function initRequest()
    {
        $this->initParamConfig();

        //init http items
        $headers = &self::loadHeaders();
        $method  = &self::loadRequestMethod();

        $this->setHeaders($headers);
        $this->setRequestMethod($method);

        //load body if need
        $accept_vars = &$this->getAcceptVars();

        if (in_array("BODY", $accept_vars))
        {
            $body    = &self::loadRequestBody(); 
            $this->setRequestBody($body);
            unset($body);
        }

        $params  = &$this->loadParams();

        if (method_exists($this, "checkParams"))
        {
            $this->checkParams();
        }

        unset($headers, $method, $params);

        return true;
    }

    /**
     * @return bool
     * @access public
     *
     */
    public function initParamConfig()
    {
        $this->paramConfig = array(
        );

        return true;
    }

    /**
     * check param from get, post or other vars
     * @return bool 
     * @throw NICED_Exception
     *
     */
    public function checkParams()
    {
        return true;
    }

    /**
     * load get and post param from client
     * @param array $accept_vars
     * @return array 
     * @access public
     * @throws
     * @todo
     * 
     */
    public function loadParams()
    {
        $accept_vars = &$this->getAcceptVars();

        foreach ($accept_vars as $k)
        {
            $k = strtoupper($k);
            if ("BODY" == $k)
            {
                $params = self::loadParamFromRequestBody($this->getRequestBody(), $this->getHeader("Content_Type"));    
            }
            else
            {
                $params = self::loadParamFromPredefinedVars($k, $this->paramConfig);
            }

            if ($params)
            {
                $loaded_params = $this->getParams();

                foreach ($params as $k => $v)
                {
                    if (!$this->getParam($k))
                    {
                        $this->setParam($k, $v);
                    }
                    else if ($v)
                    {
                        $this->setParam($k, $v);
                    }
                }
            }
        }

        return true;
    }

    public function getAcceptVars()
    {
        return $this->acceptVars;
    }

    public function setAcceptVars(Array $vars)
    {
        foreach ($vars as $k => $v)
        {
            $vars[$k] = strtoupper($v);
        }

        $this->acceptVars = $vars;
    }

    /**
     * @return array 
     * @access public 
     */
    public function getParams()
    {
        return $this->params;
    }

    /**
     * @param array
     * @return bool 
     * @access public 
     */
    public function setParams(Array $params)
    {
        $this->params = $params; 
    }

    /**
     * @param string $k
     * @param string mixed
     * @return bool
     * @access public 
     */
    public function setParam($k, $v)
    {
        $this->params[$k] = $v;

        return true;
    }

    /**
     * @param string $k
     * @return string
     * @access privte
     *
     */
    public function getParam($k)
    {
        if (isset($this->params[$k]))
        {
            return $this->params[$k];
        }
        else
        {
            return NULL;
        }
    }

    /**
     * @return string
     * @access public
     *
     */
    public function loadRequestMethod()
    {
        return isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL;
    }


    /**
     * get http method 
     * @return string
     * @access public 
     *
     */
    public function getRequestMethod()
    {
        return $this->requestMethod;
    }

    /**
     * set http method 
     * @param string $method
     * @return bool
     * @access public 
     * @throws NICED_Exception
     *
     */
    public function setRequestMethod($method)
    {
        $method = strtoupper($method);
        if (!$method)
        {
            return false;
        }

        if (!in_array($method, $this->requestMethods))
        {
            $this->handle(new NICED_Exception("method invalid"));
        }    
        $this->requestMethod = $method; 

        return true;
    }


    /**
     * load from $_POST
     * @param string $name
     * @return array 
     * @static
     * @access public 
     *
     */
    public static function loadParamFromPredefinedVars($var, $param_config)
    {
        $params = array();
        $param_config = &$param_config;
        $keys   = array_keys($param_config);

        foreach ($keys as $k)
        {
            $params[$k] = Niced_Request::loadParamFromVar($k, isset($param_config[$k]["default"]) ? $param_config[$k]["default"] : NULL, isset($param_config[$k]["filter"]) ? $param_config[$k]["filter"] : NULL, $var);
        } 

        unset($keys);

        return $params;
    }

    /**
     * parse param from body
     * @param string $body
     * @param string $content_type
     * @return array
     * @access public
     * @static
     *
     */
    public static function loadParamFromRequestBody($body, $content_type = NULL)
    {
        $params = array();

        if (!$body)
        {
            return $params;
        }

        if (stripos($content_type, "json"))
        {
            $params = json_decode($body, true);                         
        }
        elseif (stripos($content_type, "xml"))
        {
             
        }
        else
        {
            $params = parse_str($body);
        }

        return $params;
    }

    /**
     * @return string
     * @access public
     *
     */
    public function getRequestBody()
    {
        return $this->requestBody; 
    }

    /**
     * @param string $body
     * @return bool
     * @access public
     *
     */
    public function setRequestBody($body)
    {
        $this->requestBody = $body;

        return true;
    }

    /**
     * @return string 
     * @static
     * @access public
     *
     */
    public static function loadRequestBody()
    {
        $body = file_get_contents("php://input");

        return $body;
    }

}//end class
